package com.zsrd.self.service.impl;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.zsrd.self.base.config.OrderNoUtils;
import com.zsrd.self.base.config.WXPaySignatureCertificateUtil;
import com.zsrd.self.base.config.WXPayUtil;
import com.zsrd.self.base.config.WxPayConfig;
import com.zsrd.self.entity.OrderDiscounts;
import com.zsrd.self.entity.SelfUser;
import com.zsrd.self.entity.SelfWxConfig;
import com.zsrd.self.mapper.OrderDiscountsMapper;
import com.zsrd.self.mapper.SelfUserMapper;
import com.zsrd.self.service.SelfWxConfigService;
import com.zsrd.self.service.WxPayService;
import com.zsrd.self.util.AESUtil;
import com.zsrd.self.util.MySM2Util;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.*;

@Service
public class WxPayServiceImpl extends ServiceImpl<OrderDiscountsMapper, OrderDiscounts> implements WxPayService {
 
    @Resource
    private WxPayConfig wxPayConfig;

    @Autowired
    private SelfUserMapper selfUserMapper;
 
    @Resource
    private CloseableHttpClient httpClient;

    @Autowired
    private SelfWxConfigService selfWxConfigService;

    /**
     * 秘钥
     */
    private  String KEY = "1234567890hijklm";

    /**
     * jsapi用户下单
     * @param
     * @param
     * @return 预支付标识
     */
    @Override
    public Map<String, Object> jsapiPay(OrderDiscounts orderDiscounts) throws IOException {
        //获取用户id
        String prices = orderDiscounts.getPrices();
        System.out.println("获取价格--------"+prices);
        String decrypt = AESUtil.decrypt(prices,KEY);
        System.out.println("获取价格解密后的--------"+prices);
        Double aDouble = Double.valueOf(decrypt);
        int je = (int) (aDouble* 100);

        // 2. 通过 code 获取用户的 OpenID
        String openId = orderDiscounts.getOpenId();
        System.out.println("支付获取openId--------"+openId);
        String unionId=orderDiscounts.getUnionId();
        System.out.println("支付获取unionId--------"+unionId);
        String orderNo="";
        LambdaQueryWrapper<OrderDiscounts> wrapper = new LambdaQueryWrapper<>();
        if (orderDiscounts.getOpenId()!=null) {
            wrapper.eq(OrderDiscounts::getOpenId,orderDiscounts.getOpenId());
        }
        OrderDiscounts orderDiscounts1 = baseMapper.selectOne(wrapper);
        if (orderDiscounts1==null){
            OrderDiscounts orderDiscounts2 = new OrderDiscounts();
            System.out.println("判断不为null新增---------------------------------------");
             orderNo = OrderNoUtils.getNo();
            System.out.println("获取订单号---------"+orderNo);
            orderDiscounts2.setCode("1");
            System.out.println("code-------------------------");
            orderDiscounts2.setPreferentialPrice(aDouble);
            orderDiscounts2.setTime(new Date());
            orderDiscounts2.setOpenId(openId);
            orderDiscounts2.setOrderNo(orderNo);
            orderDiscounts2.setIsCoupons(orderDiscounts.getIsCoupons());
            baseMapper.insert(orderDiscounts2);
        }else {
            System.out.println("判断不为null修改---------------------------------------");
            orderNo = OrderNoUtils.getNo();
            orderDiscounts1.setCode("1");
            orderDiscounts1.setPreferentialPrice(aDouble);
            orderDiscounts1.setTime(new Date());
            orderDiscounts1.setOpenId(openId);
            orderDiscounts1.setOrderNo(orderNo);
            orderDiscounts1.setIsCoupons(orderDiscounts.getIsCoupons());
            baseMapper.updateById(orderDiscounts1);
        }
         //获取user表里的uid
        LambdaQueryWrapper<SelfUser> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(SelfUser::getUnionId,unionId);
        SelfUser selfUser = selfUserMapper.selectOne(wrapper1);
        if (selfUser!=null) {
            selfUser.setOfficialId(openId);
            selfUserMapper.updateById(selfUser);
        }
        System.out.println("修改user表unionId---------------------------------------");
        //调用统一下单API
        LambdaQueryWrapper<SelfWxConfig> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(SelfWxConfig::getOperFlag,"jsapi");
        wrapper2.eq(SelfWxConfig::getTagType,"2");
        SelfWxConfig one = selfWxConfigService.getOne(wrapper2);
        HttpPost httpPost = new HttpPost(one.getPostUrl());
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");

        try {

            LambdaQueryWrapper<SelfWxConfig> wrapper3 = new LambdaQueryWrapper<>();
            wrapper3.eq(SelfWxConfig::getOperFlag,"getBody");
            wrapper3.eq(SelfWxConfig::getTagType,"3");
            SelfWxConfig one1 = selfWxConfigService.getOne(wrapper3);

            System.out.println("----------"+wxPayConfig.getMchId()+"-----------------");
            //微信支付参数
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("mchid",one1.getAppSecret())
                    .put("appid", one1.getAppId())
                    .put("description", "社工证课程")
                    .put("notify_url", one1.getPostUrl())//todo
                    .put("out_trade_no", orderNo);
            rootNode.putObject("amount")
//                    .put("total",je);
//                    .put("total_fee",je)
            .put("total",je);
            rootNode.putObject("payer")
                    .put("openid", openId);
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            //获取对于的微信支付认证并发送请求
            CloseableHttpResponse response = httpClient.execute(httpPost);
            //微信支付返回信息
            String bodyAsString = EntityUtils.toString(response.getEntity());
            String prepayId = JSONObject.parseObject(bodyAsString).getString("prepay_id");
            System.out.println(prepayId);
            //返回调起支付的信息
//            Map<String, Object> payment = getPayment("prepay_id=" + prepayId, wxPayConfig.getAppid(), wxPayConfig.getPrivateKey(wxPayConfig.getPath()));
            Long timestamp = System.currentTimeMillis() / 1000;
            //随机字符串 这个是微信支付maven自带的 也可以用其它的
            //这个是v2支付依赖自带的工具包 可以去掉了
            String nonceStr = RandomStringUtils.randomAlphanumeric(32);
            //生成带签名支付信息
            String paySign = WXPaySignatureCertificateUtil.jsApiPaySign(String.valueOf(timestamp), nonceStr, prepayId);
            Map<String, Object> param = new HashMap<>();

            param.put("appId", one1.getAppId());
            param.put("timeStamp", String.valueOf(timestamp));
            param.put("nonceStr", nonceStr);
            param.put("package","prepay_id="+prepayId);
            param.put("signType", "RSA");
            param.put("paySign", paySign);
            param.put("code","200");
            param.put("message","下单成功");
            param.put("orderNo",orderNo);
            return param;
        } catch (Exception e) {
            throw new RuntimeException("支付失败"+e.getMessage());
        }
    }

    /**
     * 获取code
     * @param code
     * @return
     */
    @Override
    public Map<String, Object> getCode(String code) {

        System.out.println(code);
        Map<String, Object> map = new HashMap<>();
        String openId = getOpenId(code);
        System.out.println("openId----------"+openId);
        String unionId="";
        if (openId != null) {
            // 3. 获取用户的 UnionID
            unionId = getUnionId(openId);
        }
        System.out.println("getCode方法的unionId--------"+unionId);
        String accessToken = getAccessToken();
        System.out.println("getCode方法的accessToken-------"+accessToken);
        map.put("accessToken",accessToken);
        map.put("openId",openId);
        map.put("unionId",unionId);
        return map;
    }

    public  String getOpenId(String code) {

        LambdaQueryWrapper<SelfWxConfig> wrapper3 = new LambdaQueryWrapper<>();
        wrapper3.eq(SelfWxConfig::getOperFlag,"getOpenId");
        wrapper3.eq(SelfWxConfig::getTagType,"2");
        SelfWxConfig one1 = selfWxConfigService.getOne(wrapper3);

        OkHttpClient client = new OkHttpClient.Builder().build();
        String url = one1.getPostUrl() +
                "appid=" + one1.getAppId() +
                "&secret=" + MySM2Util.decrypt(one1.getAppSecret()) +
                "&code=" + code +
                "&grant_type=authorization_code";

        Request request = new Request.Builder()
                .url(url)
                .build();

        try {
            Response response = client.newCall(request).execute();
            String responseBody = response.body().string();
            JSONObject json = JSON.parseObject(responseBody);
            if (json.containsKey("openid")) {
                return json.getString("openid");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public  String getUnionId(String openId) {

        LambdaQueryWrapper<SelfWxConfig> wrapper3 = new LambdaQueryWrapper<>();
        wrapper3.eq(SelfWxConfig::getOperFlag,"getUnionId");
        wrapper3.eq(SelfWxConfig::getTagType,"2");
        SelfWxConfig one1 = selfWxConfigService.getOne(wrapper3);


        OkHttpClient client = new OkHttpClient();
        String url = one1.getPostUrl() +
                "access_token=" + getAccessToken() +
                "&openid=" + openId +
                "&lang=zh_CN";
        Request request = new Request.Builder()
                .url(url)
                .build();

        try {
            Response response = client.newCall(request).execute();
            String responseBody = response.body().string();
            JSONObject json = JSON.parseObject(responseBody);
            if (json.containsKey("unionid")) {
                return json.getString("unionid");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public  String getAccessToken() {

        LambdaQueryWrapper<SelfWxConfig> wrapper3 = new LambdaQueryWrapper<>();
        wrapper3.eq(SelfWxConfig::getOperFlag,"getAccessToken");
        wrapper3.eq(SelfWxConfig::getTagType,"2");
        SelfWxConfig one1 = selfWxConfigService.getOne(wrapper3);

        OkHttpClient client = new OkHttpClient();
        String url = one1.getPostUrl() +
                "grant_type=client_credential" +
                "&appid=" + one1.getAppId() +
                "&secret=" + MySM2Util.decrypt(one1.getAppSecret());
        Request request = new Request.Builder()
                .url(url)
                .build();

        try {
            Response response = client.newCall(request).execute();
            String responseBody = response.body().string();
            JSONObject json = JSON.parseObject(responseBody);
            if (json.containsKey("access_token")) {
                String access_token = json.getString("access_token");
                System.out.println(access_token);
                return json.getString("access_token");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }





 
}